package com.wingsboat.common.core.utils.text;

import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;

public class DataConverter {
    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte[] buf) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexString
     * @return
     */
    public static String parseHexStr2Byte(String hexString) {
        //16进制转10进制
        BigInteger sint = new BigInteger(hexString, 16);
        //10进制转2进制
        String result = sint.toString(2);
        return new StringBuilder(result).toString();
    }

    /**
     * 将16进制转换为十进制
     *
     * @param hexString
     * @return
     */
    public static int parseHexStr2Integer(String hexString) {
        int h = Integer.parseInt(hexString, 16);
        return h;
    }

    /**
     * 将 4字节的16进制字符串，转换为32位带符号的十进制
     * @param strHex
     * @return
     */
    public static int parseSignedHex2Integer(String strHex){
        if(strHex.length()==0){
            return 0;
        }
        int x = 0;
        //带符号十六进制转换十进制
        String fristNum = strHex.substring(0, 1);
        String hexStr2Byte = parseHexStr2Byte(fristNum);
        String flag = hexStr2Byte.substring(0, 1);
        if("1".equals(flag)){
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < strHex.length(); i++) {
                String num = strHex.substring(i, i+1);
                int decNum = Integer.parseInt(num,16);
                int a = decNum^15;
                sb.append(parseInteger2Hex(a));
            }
            x = -Integer.parseInt(sb.toString(),16)-1;
        }else{
            x = Integer.parseInt(strHex,16);
        }

        return x;

    }

    //十进制转16进制
    public static String parseInteger2Hex(int n) {
        StringBuffer s = new StringBuffer();
        String a;
        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n != 0){
            s = s.append(b[n%16]);
            n = n/16;
        }
        a = s.reverse().toString();
        return a;
    }

    //十进制转16进制
    public static String parseInteger2Hex(int n,int length) {
        StringBuffer s = new StringBuffer();
        String a;
        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n != 0){
            s = s.append(b[n%16]);
            n = n/16;
        }
        a = s.reverse().toString();
        return StringUtils.leftPad(a, length, '0');
    }



    /**
     * 将 4字节的16进制字符串，转换为32位带符号的十进制浮点型
     * @param str 4字节 16进制字符
     * @return
     */
    public  static  float parseHex2Float(String str){
        return  Float.intBitsToFloat(new BigInteger(str, 16).intValue());
    }

    /**
     * 将带符号的32位浮点数装换为16进制
     * @param value
     * @return
     */
    public  static  String parseFloat2Hex(Float value){
        return  Integer.toHexString(Float.floatToIntBits(value));
    }

    /**
     * 将 2字节的16进制字符串，转换为16位带符号的十进制short
     * @param str
     * @return
     */
    public static short parseSignedHex2Short(String str){
        return Integer.valueOf(str,16).shortValue();
    }


    /**
     * 十六进制字符串高低位转换
     * @param hex
     * @return
     */
    public static String reverseHex(String hex) {
        char[] charArray = hex.toCharArray();
        int length = charArray.length;
        int times = length / 2;
        for (int c1i = 0; c1i < times; c1i += 2) {
            int c2i = c1i + 1;
            char c1 = charArray[c1i];
            char c2 = charArray[c2i];
            int c3i = length - c1i - 2;
            int c4i = length - c1i - 1;
            charArray[c1i] = charArray[c3i];
            charArray[c2i] = charArray[c4i];
            charArray[c3i] = c1;
            charArray[c4i] = c2;
        }
        return new String(charArray);
    }

    public static String addSpace(String replace) {
        String regex = "(.{2})";
        replace = replace.replaceAll(regex, "$1 ");
        return replace;
    }

    /**
     * @Title:bytes2HexString
     * @Description:字节数组转16进制字符串
     * @param b
     *            字节数组
     * @return 16进制字符串
     * @throws
     */
    public static String bytes2HexString(byte[] b) {
        StringBuffer result = new StringBuffer();
        String hex;
        for (int i = 0; i < b.length; i++) {
            hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            result.append(hex.toUpperCase());
        }
        return result.toString();
    }
    /**
     * @Title:hexString2Bytes
     * @Description:16进制字符串转字节数组
     * @param src  16进制字符串
     * @return 字节数组
     */
    public static byte[] hexString2Bytes(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }
    /**
     * @Title:string2HexString
     * @Description:字符串转16进制字符串
     * @param strPart  字符串
     * @return 16进制字符串
     */
    public static String string2HexString(String strPart) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < strPart.length(); i++) {
            int ch = (int) strPart.charAt(i);
            String strHex = Integer.toHexString(ch);
            hexString.append(strHex);
        }
        return hexString.toString();
    }
    /**
     * @Title:hexString2String
     * @Description:16进制字符串转字符串
     * @param src
     *            16进制字符串
     * @return 字节数组
     * @throws
     */
    public static String hexString2String(String src) {
        String temp = "";
        for (int i = 0; i < src.length() / 2; i++) {
            //System.out.println(Integer.valueOf(src.substring(i * 2, i * 2 + 2),16).byteValue());
            temp = temp+ (char)Integer.valueOf(src.substring(i * 2, i * 2 + 2),16).byteValue();
        }
        return temp;
    }

    /**
     * @Title:char2Byte
     * @Description:字符转成字节数据char-->integer-->byte
     * @param src
     * @return
     * @throws
     */
    public static Byte char2Byte(Character src) {
        return Integer.valueOf((int)src).byteValue();
    }

    /**
     * @Title:intToHexString
     * @Description:10进制数字转成16进制
     * @param a 转化数据
     * @param len 占用字节数
     * @return
     * @throws
     */
    public static String intToHexString(int a,int len){
        len<<=1;
        String hexString = Integer.toHexString(a);
        int b = len -hexString.length();
        if(b>0){
            for(int i=0;i<b;i++)  {
                hexString = "0" + hexString;
            }
        }
        return hexString;
    }


    /**
     * 将16进制的2个字符串进行异或运算
     * http://blog.csdn.net/acrambler/article/details/45743157
     * @param strHex_X
     * @param strHex_Y
     * 注意：此方法是针对一个十六进制字符串一字节之间的异或运算，如对十五字节的十六进制字符串异或运算：1312f70f900168d900007df57b4884
    先进行拆分：13 12 f7 0f 90 01 68 d9 00 00 7d f5 7b 48 84
    13 xor 12-->1
    1 xor f7-->f6
    f6 xor 0f-->f9
    ....
    62 xor 84-->e6
    即，得到的一字节校验码为：e6
     * @return
     */
    public static String xor(String strHex_X,String strHex_Y){
        //将x、y转成二进制形式
        String anotherBinary=Integer.toBinaryString(Integer.valueOf(strHex_X,16));
        String thisBinary=Integer.toBinaryString(Integer.valueOf(strHex_Y,16));
        String result = "";
        //判断是否为8位二进制，否则左补零
        if(anotherBinary.length() != 8){
            for (int i = anotherBinary.length(); i <8; i++) {
                anotherBinary = "0"+anotherBinary;
            }
        }
        if(thisBinary.length() != 8){
            for (int i = thisBinary.length(); i <8; i++) {
                thisBinary = "0"+thisBinary;
            }
        }
        //异或运算
        for(int i=0;i<anotherBinary.length();i++){
            //如果相同位置数相同，则补0，否则补1
            if(thisBinary.charAt(i)==anotherBinary.charAt(i))
                result+="0";
            else{
                result+="1";
            }
        }
        return Integer.toHexString(Integer.parseInt(result, 2));
    }


    /**
     *  Convert byte[] to hex string.这里我们可以将byte转换成int
     * @param src byte[] data
     * @return hex string
     */
    public static String bytes2Str(byte[] src){
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
    /**
     * @return 接收字节数据并转为16进制字符串
     */
    public static String receiveHexToString(byte[] by) {
        try {
            /*io.netty.buffer.WrappedByteBuf buf = (WrappedByteBuf)msg;
            ByteBufInputStream is = new ByteBufInputStream(buf);
            byte[] by = input2byte(is);*/
            String str = bytes2Str(by);
            str = str.toLowerCase();
            return str;
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("接收字节数据并转为16进制字符串异常");
        }
        return null;
    }

    /**
     * "7dd",4,'0'==>"07dd"
     * @param input 需要补位的字符串
     * @param size 补位后的最终长度
     * @param symbol 按symol补充 如'0'
     * @return
     * N_TimeCheck中用到了
     */
    public static String fill(String input, int size, char symbol) {
        while (input.length() < size) {
            input = symbol + input;
        }
        return input;
    }


    /**
     * 16进制转图片
     * @param src
     * @param output
     */
    public static void saveToImgFile(String src,String output){
        if(src==null||src.length()==0){
            return;
        }
        try{
            FileOutputStream out = new FileOutputStream(new File(output));
            byte[] bytes = src.getBytes();
            for(int i=0;i<bytes.length;i+=2){
                out.write(charToInt(bytes[i])*16+charToInt(bytes[i+1]));
            }
            out.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private static int charToInt(byte ch){
        int val = 0;
        if(ch>=0x30&&ch<=0x39){
            val=ch-0x30;
        }else if(ch>=0x41&&ch<=0x46){
            val=ch-0x41+10;
        }
        return val;
    }

    public static  int byte2ToInt(byte b1,byte b2){
        int temp1 = b1&0xff ;
        int temp2 = b2&0xff ;
        return (temp1<< 8) + temp2;
    }
    public static  int byte4ToInt(byte b1,byte b2,byte b3,byte b4){

        int temp1 = b1&0xff ;
        int temp2 = b2&0xff ;
        int temp3 = b3&0xff ;
        int temp4 = b4&0xff ;
        return (temp1 << 24) + (temp2<< 16)+(temp3<< 8)+temp4;
    }


    public static void writeBits(Integer cache,int value,int start,int length){
        int intValue = cache.intValue();
    }


    public static Long hex2Long(String hexStr){
       return  Long.parseLong(hexStr, 16);
    }
}
